<?php
/**
 * Copyright 2011  SURFfoundation
 * 
 * This file is part of ESCAPE.
 * 
 * ESCAPE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * ESCAPE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with ESCAPE.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * For more information:
 * http://escapesurf.wordpress.com/
 * http://www.surffoundation.nl/
 * 
 * Contact: d.vierkant@utwente.nl
 * 
 * @license http://www.gnu.org/licenses/gpl.html GNU GPLv3
 */
?>
<?php
/**
 * Inverse Functional Property data source
 * 
 * Returns aggregated resources containing an inverse functional property equal to the query entity.
 */
class escape_entityresolution_datasource_Ifp extends escape_entityresolution_datasource_Aggregation
{
	/**
	 * Get a block (of entities) matching the entity specified.
	 * @param entityresolution_Entity $entity
	 * @param entityresolution_EntityFactory $entityFactory
	 * @return entityresolution_Block $block
	 */
	public function getBlock($entity, $entityFactory)
	{
		$block = new entityresolution_Block();
		
		$inverseFunctionalPropertyValues = array();
		
		$properties = $entity->getProperties();
		foreach($properties as $property)
		{
			/* @var $property entityresolution_Property */
			
			$predicateForms = $property->getPredicateForms();
			
			foreach($predicateForms as $predicate)
			{
				$isOwlInverseFunctionalProperty = $this->repository->repositorySchema->isOwlInverseFunctionalProperty($predicate);
				
				if($isOwlInverseFunctionalProperty)
				{
					foreach($predicateForms as $predicateForm)
					{
						$values = $property->getValues();
						foreach($values as $value)
						{
							/* @var $value entityresolution_Value */
							
							if(!isset($inverseFunctionalPropertyValues[$predicateForm]))
							{
								$inverseFunctionalPropertyValues[$predicateForm] = $value->getValueForms();
							}
							else
							{
								$inverseFunctionalPropertyValues[$predicateForm] = array_merge($inverseFunctionalPropertyValues[$predicateForm], $value->getValueForms());
							}
						}
					}
					
					break;
				}
			}
		}
		
//		print_r($inverseFunctionalPropertyValues);
		
		if(count($inverseFunctionalPropertyValues) > 0)
		{
			$sparqlPatterns = array();
			foreach($inverseFunctionalPropertyValues as $predicate => $values)
			{
				foreach($values as $value)
				{
					$valueType = simplerdf_Util::guessType($value);
					if($valueType === 'literal')
					{
						$sparqlPatterns[] = '{ ?s <' . $this->repository->tripleStore->sparqlEscapeUri($predicate) . '> "' . $this->repository->tripleStore->sparqlEscapeLiteral($value) . '" }';
					}
					else
					{
						$sparqlPatterns[] = '{ ?s <' . $this->repository->tripleStore->sparqlEscapeUri($predicate) . '> <' . $this->repository->tripleStore->sparqlEscapeUri($value) . '> }';
					}
				}
			}
			$sparqlPattern = implode(' UNION ', $sparqlPatterns);
			
			$sparqlQuery  = "select distinct ?s\n";
			$sparqlQuery .= "where\n";
			$sparqlQuery .= "{\n";
			$sparqlQuery .= "	<" . $this->repository->tripleStore->sparqlEscapeUri($this->aggregation->getUri()) . "> <http://www.openarchives.org/ore/terms/aggregates> ?s \n";
			$sparqlQuery .= "	" . $sparqlPattern . "\n";
			$sparqlQuery .= "}\n";
			
			$sparqlResultSet = $this->repository->tripleStore->sparqlSelect($sparqlQuery);
			$results = $sparqlResultSet->getResults();
			$uris = array();
			foreach($results as $result)
			{
				$uris[] = $result['s']['value']; 
			}
			
			foreach($uris as $uri)
			{
				$aggregatedResource = $this->repository->getOreAggregatedResourceByUri($uri);
				
				$rdfResource = $aggregatedResource->getProperties();
				$rdfDocument = simplerdf_RdfSchemaDocument::createRdfDocument();
				$rdfDocument->addResource($rdfResource);
				
				$entity = $entityFactory->createEntity($rdfDocument, $rdfResource->getSubject());
						
				$blockEntry = new entityresolution_BlockEntry();
				$blockEntry->setEntity($entity);
				$blockEntry->setScore(0.0);
				
				$block->addEntry($blockEntry);
			}
		}
		
		return $block;
	}
}